import { observer } from 'mobx-react-lite';
import Navbar from '@/components/Navbar';
import { View, Image, ScrollView, Input } from '@tarojs/components';
import systemStore from '@/stores/SystemStore';
import './index.less';
import { useEffect, useMemo, useState } from 'react';
import {
  createSelectorQuery,
  nextTick,
  hideKeyboard,
  showToast,
  useDidShow,
} from '@tarojs/taro';
import AddIconImg from '@/static/images/icon/add.png';
import PictureImg from '@/static/images/icon/picture.png';
import VideoImg from '@/static/images/icon/video.png';
import ButtonComp from '@/components/Button';
import ImageComp from '@/components/Image';
import ChatBusiness from '@/business/ChatBusiness';
import authStore from '@/stores/AuthStore';
import AuthConstant from '@/constant/AuthConstant';
import BusinessConstant from '@/constant/BusinessConstant';
import chatStore from '@/stores/ChatStore';
import { ChatEntity } from '@/entities/ChatEntity';
import { CommonUtil } from '@/utils/CommonUtil';
import { eventCenter } from '@tarojs/runtime';
import EventConstant from '@/constant/EventConstant';
import socketStore from '@/stores/SocketStore';
import {
  ImagePreview,
  PullToRefresh,
  Uploader,
  Video,
} from '@nutui/nutui-react-taro';
import ImageConstant from '@/constant/ImageConstant';
import CodeConstant from '@/constant/CodeConstant';

function ChatMessage() {
  const { identity } = authStore;
  const {
    chatSender,
    chatReceiver,
    chatMessageList,
    setChatMessageList,
    setCurrentChatSession,
    currentChatSession,
    senderId,
  } = chatStore;
  const { websocketInstance } = socketStore;
  // 键盘高度
  const [keyboardHeight, setKeyboardHeight] = useState(0);
  // 输入框的高度
  const [chatInputHeight, setChatInputHeight] = useState(0);
  // 输入框的内容
  const [chatInputVal, setChatInputVal] = useState('');
  const [receiverId, setReceiverId] = useState('');
  const [scrollView, setScrollView] = useState<any>();
  const [inputFocus, setInputFocus] = useState(false);
  // 消息记录的页数
  const [messagePage, setMessagePage] = useState(1);
  // 是否继续获取信息
  const [continueGetMessage, setContinueGetMessage] = useState(true);
  // 发送其他消息popup面板
  const [otherMessageVisible, setOtherMessageVisible] = useState(false);
  // 发送其他消息popup面板高度
  const [otherMessageHeight] = useState(150);
  const [currentImagePreview, setCurrentImagePreview] =
    useState<Array<{ src: string }>>();
  const [videoPreview, setVideoPreview] = useState<{
    src: string;
    type: string;
  }>();
  const [imagePreviewVisible, setImagePreviewVisible] = useState(false);
  const [videoPreviewVisible, setVideoPreviewVisible] = useState(false);

  /**
   * 处理图片点击
   */
  const handlePicture = () => {};

  /**
   * 处理视频点击
   */
  const handleVideo = () => {};

  /**
   * 发送其他内容
   */
  const sendOtherDomainList = useMemo(
    () => [
      {
        className: 'picture-wrap',
        icon: PictureImg,
        handleClick: handlePicture,
        sourceType: 'album',
      },
      {
        className: 'video-wrap',
        icon: VideoImg,
        handleClick: handleVideo,
        sourceType: 'camera',
      },
    ],
    []
  );

  /**
   * 接收最新的一条消息
   */
  const receiveLastOneMessage = async () => {
    if (!senderId || !receiverId) return;
    // 获取当前会话的最新一条消息
    const lastOneMessage: any =
      await ChatBusiness.getCurrentChatSessionLastOneMessage(
        senderId,
        receiverId
      );
    // 查找一下lastOneMessage是否已经存在chatMessageList
    if (!chatMessageList?.find((m) => m.id === lastOneMessage.id))
      setChatMessageList([...chatMessageList, lastOneMessage]);
    nextTick(() => {
      scrollView?.scrollIntoView('#signBottom');
    });
  };

  useDidShow(() => {
    receiveLastOneMessage();
  });

  useEffect(() => {
    if (receiverId && scrollView) {
      eventCenter.off(EventConstant.GET_CURRENT_LAST_ONE_MESSAGE);
      eventCenter.on(
        EventConstant.GET_CURRENT_LAST_ONE_MESSAGE,
        receiveLastOneMessage
      );
    }
  }, [receiverId, scrollView]);

  useEffect(() => {
    if (identity === AuthConstant.LANDLORD) {
      // 说明发送者是房东，接收者是租客
      setReceiverId(`${BusinessConstant.SIGN_TENANT},${chatReceiver?.id}`);
    } else if (identity === AuthConstant.TENANT) {
      // 说明发送者是租客，接收者是房东
      setReceiverId(`${BusinessConstant.SIGN_LANDLORD},${chatReceiver?.id}`);
    }
    createSelectorQuery()
      .select('.chat-message-wrap')
      .node()
      .exec((res) => {
        const scrollView = res[0].node;
        setScrollView(scrollView);
      });
    createSelectorQuery()
      .select('.chat-input-wrap')
      .boundingClientRect()
      .exec((res) => {
        setChatInputHeight(res[0].height);
      });
    return () => {
      eventCenter.off(EventConstant.GET_CURRENT_LAST_ONE_MESSAGE);
      eventCenter.trigger(
        EventConstant.CHAT_MESSAGE_BACK,
        chatStore.currentChatSession
      );
      chatStore.clearChatMessageList();
    };
  }, []);

  /**
   * 获取当前会话中的聊天记录
   */
  const getChatMessage = async () => {
    if (senderId && receiverId && continueGetMessage) {
      const chat: any = await ChatBusiness.getChatMessage(
        senderId,
        receiverId,
        messagePage,
        10
      );
      if (chat?.length) {
        // 服务器有数据返回
        if (chatMessageList?.length) {
          // chatMessage有数据
          setChatMessageList([...chat, ...chatMessageList]);
        } else {
          // chatMessage无数据
          setChatMessageList([...chat]);
        }
      } else {
        // 服务器没有数据返回，则说明记录已经全部加载完
        setContinueGetMessage(false);
      }
      setMessagePage(messagePage + 1);
    }
  };

  /**
   * 添加一个聊天会话
   */
  const addChatSession = async () => {
    if (senderId && receiverId) {
      const res: any = await ChatBusiness.addChatSession(senderId, receiverId);
      setCurrentChatSession(res);
    }
  };

  useEffect(() => {
    addChatSession();
    getChatMessage();
  }, [receiverId]);

  /**
   * 处理发送消息
   */
  const sendMessage = async (
    chatType: number = BusinessConstant.CHAT_TYPE_TEXT,
    content: string = chatInputVal
  ) => {
    const chat: any = await ChatBusiness.addChatMessage({
      sessionId: currentChatSession?.id!,
      senderId: senderId,
      receiverId: receiverId,
      content,
      type: chatType,
    });
    // 存入store
    chatMessageList?.length
      ? setChatMessageList([...chatMessageList, chat])
      : setChatMessageList([chat]);
    // 清空消息输入框信息
    setChatInputVal('');
    setInputFocus(true);
    nextTick(() => {
      scrollView?.scrollIntoView('#signBottom');
    });
    const [identity, id] = receiverId.split(',');
    // websocket 通知接收者
    websocketInstance?.send({
      data: JSON.stringify({
        toIdentity:
          identity === BusinessConstant.SIGN_TENANT
            ? AuthConstant.TENANT
            : AuthConstant.LANDLORD,
        toId: Number(id),
        active: BusinessConstant.SOCKET_GET_CHAT_MESSAGE,
      }),
    });
  };

  /**
   * 处理输入框聚焦
   * @param height
   */
  const handleInputFocus = ({ detail: { height } }) => {
    setInputFocus(true);
    setKeyboardHeight(height);
    setOtherMessageVisible(false);
    nextTick(() => {
      scrollView?.scrollIntoView('#signBottom');
    });
  };

  /**
   * 处理输入框失焦
   */
  const handleInputBlur = () => {
    setInputFocus(false);
    setKeyboardHeight(0);
    setOtherMessageVisible(false);
  };

  /**
   * 点击了聊天信息区，则将输入框失焦
   */
  const handleScrollClick = () => {
    setInputFocus(false);
    setOtherMessageVisible(false);
  };

  // 等 chatInputHeight 的高度变化确定之后，再进行滚动
  useEffect(() => {
    nextTick(() => {
      scrollView?.scrollIntoView('#signBottom');
    });
  }, [chatInputHeight]);

  /**
   * 发送其他消息
   */
  const sendOtherMessgae = async () => {
    // 隐藏键盘
    await hideKeyboard();
    nextTick(() => {
      setOtherMessageVisible(true);
    });
  };

  /**
   * 媒体上传成功（图片视频）
   */
  const mediumUploadSuccess = (responseText: any) => {
    let chatType = BusinessConstant.CHAT_TYPE_TEXT;
    const res = JSON.parse(responseText.data);
    if (res.code !== CodeConstant.SUCCESS) {
      showToast({ title: '发送失败！', icon: 'error' });
      return;
    }
    const { src, mimeType } = res.data;
    const type = mimeType?.split('/')[0];
    if (type === 'video') {
      // 视频
      chatType = BusinessConstant.CHAT_TYPE_VIDEO;
    } else if (type === 'image') {
      // 图片
      chatType = BusinessConstant.CHAT_TYPE_IMAGE;
    }
    // 发送消息
    sendMessage(chatType, src);
  };

  /**
   * 查看图片
   * @param images
   * @param idx
   */
  const toLookImage = (images: string[]) => {
    setCurrentImagePreview(
      images.map((src: string) => ({
        src: `${ImageConstant.SERVER_ROOT}/${src}`,
      }))
    );
    setImagePreviewVisible(true);
  };

  /**
   * 图片点击
   */
  const clickImage = () => {
    setImagePreviewVisible(false);
  };

  /**
   * 查看视频
   * @param video
   */
  const toLookVideo = (video: string) => {
    setVideoPreview({
      src: `${ImageConstant.SERVER_ROOT}/${video}`,
      type: 'video/mp4',
    });
    setVideoPreviewVisible(true);
  };

  /**
   * 视频点击
   */
  const clickVideo = () => {
    setVideoPreviewVisible(false);
    nextTick(() => {
      scrollView?.scrollIntoView('#signBottom');
    });
  };

  return (
    <Navbar title={chatReceiver?.name} mode='back' bgColor='var(--mini-first)'>
      <View
        className='user-chat-container'
        style={{
          height: `calc(${systemStore.haveNavbarNotTabbarHeight} - ${keyboardHeight}px)`,
        }}
      >
        <ScrollView
          className='chat-message-wrap'
          style={{
            height: `calc(100% - ${chatInputHeight}px - ${
              otherMessageVisible ? otherMessageHeight : 0
            }px)`,
          }}
          scrollY={true}
          showScrollbar={false}
          enhanced={true}
          onClick={handleScrollClick}
        >
          <PullToRefresh
            completeText='加载完成'
            pullingText='下拉加载历史记录'
            canReleaseText=' '
            completeDelay={200}
            refreshingText='加载中'
            onRefresh={() =>
              new Promise(async (resolve) => {
                await getChatMessage();
                resolve('');
              })
            }
            className='pull-to-refresh'
          >
            {chatMessageList?.map(
              (chatMessage: ChatEntity.IChatMessage, idx: number) => {
                const preDate =
                  idx === 0 ? new Date() : chatMessageList[idx - 1]?.createdAt;
                return (
                  <View key={chatMessage.id} className='message-wrap'>
                    <View className='chat-message-date'>
                      {CommonUtil.isCertainMinuteAge(
                        chatMessage.createdAt,
                        preDate,
                        3 * 60 * 1000
                      ) || idx === 0 ? (
                        <View className='date-content'>
                          {CommonUtil.formatChatDate(chatMessage.createdAt)}
                        </View>
                      ) : null}
                    </View>
                    {senderId == chatMessage.senderId ? (
                      <View className='own-wrap'>
                        {chatMessage.type ===
                        BusinessConstant.CHAT_TYPE_TEXT ? (
                          <View className='text-box'>
                            {chatMessage.content}
                          </View>
                        ) : chatMessage.type ===
                          BusinessConstant.CHAT_TYPE_IMAGE ? (
                          <ImageComp
                            className='img-box'
                            src={chatMessage.content}
                            mode='heightFix'
                            onClick={() => toLookImage([chatMessage.content])}
                          />
                        ) : (
                          <ImageComp
                            className='video-box'
                            src={ImageConstant.DEFAULT_VIDEO_COVER_IMG}
                            mode='heightFix'
                            onClick={() => toLookVideo(chatMessage.content)}
                          />
                        )}
                        <ImageComp
                          className='head-img'
                          src={chatSender?.headImg}
                        />
                      </View>
                    ) : (
                      <View className='other-wrap'>
                        <ImageComp
                          className='head-img'
                          src={chatReceiver?.headImg}
                        />
                        {chatMessage.type ===
                        BusinessConstant.CHAT_TYPE_TEXT ? (
                          <View className='text-box'>
                            {chatMessage.content}
                          </View>
                        ) : chatMessage.type ===
                          BusinessConstant.CHAT_TYPE_IMAGE ? (
                          <ImageComp
                            className='img-box'
                            src={chatMessage.content}
                            mode='heightFix'
                            onClick={() => toLookImage([chatMessage.content])}
                          />
                        ) : (
                          <ImageComp
                            className='video-box'
                            src={ImageConstant.DEFAULT_VIDEO_COVER_IMG}
                            onClick={() => toLookVideo(chatMessage.content)}
                          />
                        )}
                      </View>
                    )}
                  </View>
                );
              }
            )}
          </PullToRefresh>
          <View id='signBottom' style={{ height: '16px' }}></View>
        </ScrollView>
        <View className='chat-input-wrap'>
          <Input
            className='text-input'
            style={{
              width: chatInputVal ? `calc(100% - 70px)` : `calc(100% - 60px)`,
            }}
            placeholder=' '
            adjustPosition={false}
            value={chatInputVal}
            onInput={({ detail: { value } }) => setChatInputVal(value)}
            holdKeyboard={true}
            focus={inputFocus}
            onFocus={handleInputFocus}
            onBlur={handleInputBlur}
            onConfirm={() => sendMessage()}
          />
          {chatInputVal ? (
            <ButtonComp
              title='发送'
              size='normal'
              className='send-btn'
              onClick={sendMessage}
            />
          ) : (
            <Image
              src={AddIconImg}
              className='add-icon'
              onClick={sendOtherMessgae}
            />
          )}
        </View>
        {otherMessageVisible ? (
          <View
            className='send-other-wrap'
            style={{ height: otherMessageHeight }}
          >
            {sendOtherDomainList.map((domain) => {
              return (
                <View className={domain.className} onClick={domain.handleClick}>
                  <Uploader
                    url={ImageConstant.CHAT_UPLOAD}
                    maxCount={1}
                    headers={{ authorization: authStore.token }}
                    sourceType={[domain.sourceType as any]}
                    onSuccess={({ responseText }) =>
                      mediumUploadSuccess(responseText)
                    }
                  >
                    <Image src={domain.icon} className='send-other-icon' />
                  </Uploader>
                </View>
              );
            })}
          </View>
        ) : null}
      </View>
      <ImagePreview
        images={currentImagePreview}
        visible={imagePreviewVisible}
        defaultValue={1}
        onClose={clickImage}
        style={{ position: 'absolute' }}
        indicator={false}
      />
      {videoPreviewVisible ? (
        <Video
          source={videoPreview}
          style={{
            height: '100vh',
            position: 'absolute',
            top: '0',
            left: '0',
            zIndex: '99',
          }}
          loop={true}
          autoplay={true}
          onClick={clickVideo}
        />
      ) : null}
    </Navbar>
  );
}

export default observer(ChatMessage);
